//==================================================
// X_NC_template.ino
// 2015-01-31
//==================================================
// Nabton Client Generic Configuration
//==================================================

// Adjust these paramaters acording to specific application
#define NFLOAT 4  // No of decimals i float value
#define SIDN  3   // No of SIDs
#define SID1 901
#define SID2 902
#define SID3 903
#define SID4 904
#define SID5 905
#define SID6 906
#define SID7 907
#define SID8 908

// Fixed part of configuration

// Arduino states
#define YES_SYNC 1
#define NO_SYNC  2
#define MAX_SID 10
#define MAX_ORDERS 100
#define PIN_LED_STATUS 13
int g_sids[10] = {SIDN,SID1,SID2,SID3,SID4,SID5,SID6,SID7,SID8};
unsigned long g_time1=0,g_time2=0,g_delta,g_now, g_last[MAX_SID];
unsigned long g_one_sec = 1000; // resolution of heartbeat =  1000 msec
int g_on[MAX_ORDERS];    // Arduino - RPi interface par type
int g_value[MAX_ORDERS]; // Arduino - RPi interface par value
int g_sidHb[MAX_SID];
int g_sidHbUnit[MAX_SID];
int g_sidDelay[MAX_SID]; // Always in sec
int g_sidCountDown[MAX_SID];
char g_errmsg[120];  // Error message
int g_error = 0;     // Error flag
char g_logmsg[120];  // Log message
int g_log = 0;       // Log flag
int g_state = NO_SYNC; 
char g_res[120];
int g_counter = 0;

// Arduino-RPi protocol
#define NABTON_DATA     1 
#define NABTON_DATA_ACK 2
#define NABTON_NODATA   3
#define NABTON_LOG      8 
#define NABTON_ERROR    9 
// Arduino Control Protocol
#define ON_HB_VAL        2
#define ON_HB_UNIT       3
#define ON_STEPPER_DIR   4
#define ON_STEPPER_STEPS 5
#define ON_STEPPER_SPEED 6

#define ERR_SID_NOT_FOUND  "SID_not_found"
#define ERR_UNSUPPORTED_MESSAGE "Unsupported_message"
#define ERR_NO_MESSAGE "No_message"
#define ERR_SID_MISMATCH "SID_Mismatch"
//=================================================
//
// D0 RX used for serial communication to server (Raspberry Pi)
// D1 TX used for serial communication to server (Raspberry Pi)
// D2
// D3 
// D4 IR Data
// D5
// D6 DIR Stepper
// D7 STEP Stepper
// D8 SLEEP Stepper
// D9 One Wire Data
// D10  RX Bluetooth device
// D11  TX Bluetooth device
// D12 
// D13  Client Status
//
// A0
// A1
// A2
// A3
// A4 SDA I2C OLED
// A5 SCL I2C OLED

// MEGA
// D20 SDA I2C OLED
// D21 SCL I2C OLED
//=================================================
//==================================================
// Nabton Client Application Configuration
//==================================================
float x=0.0;
//==================================================
// OLED I2C
//==================================================
#include <U8glib.h>
//U8GLIB_SSD1306_128X64 u8g(13, 11, 10, 9);// SW SPI protocol(4 pins): SCK = 13, MOSI = 11, CS = 10, A0 = 9	
//U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_NONE); // Small display I2C protocol (2 pins)
U8GLIB_SH1106_128X64 u8g(U8G_I2C_OPT_NONE); // Large display
char dl[5][8],dm[5][8],dr[5][8];
//=================================================
void draw()
//=================================================
{
  // Horizontal pixels: 0 - 120
  // Vertical pixels: 0 - 63
  //u8g.setFont(u8g_font_6x10);
  u8g.setFont(u8g_font_unifont);
  //u8g.setFont(u8g_font_osb21);
  /*u8g.drawStr( 0, 1, ".....");
  u8g.drawStr( 45, 1, ".....");
  u8g.drawStr( 90, 1, ".....");
  
  u8g.drawStr( 0, 63, "_____");
  u8g.drawStr( 45,63, "_____");
  u8g.drawStr( 90,63, "_____");*/
  
  u8g.drawStr( 0, 10, dl[1]);
  u8g.drawStr( 0, 27, dl[2]);
  u8g.drawStr( 0, 45, dl[3]);
  u8g.drawStr( 0, 62, dl[4]);

  u8g.drawStr( 45, 10, dm[1]);
  u8g.drawStr( 45, 27, dm[2]);
  u8g.drawStr( 45, 45, dm[3]);
  u8g.drawStr( 45, 62, dm[4]);

  u8g.drawStr( 90, 10, dr[1]);
  u8g.drawStr( 90, 27, dr[2]);
  u8g.drawStr( 90, 45, dr[3]);
  u8g.drawStr( 90, 62, dr[4]);  

}
//=================================================
void NB_serialFlush()
//=================================================
{
  //Serial.print("flush:"); 
  while(Serial.available() > 0) {
    char t = Serial.read();
    //Serial.print(t); 
  }
  //Serial.println(":flushed"); 
}   
//=================================================
void NB_printFloat(float value, int places) 
//=================================================
{
  int digit;
  float tens = 0.1;
  int tenscount = 0;
  int i;
  float tempfloat = value;
  float d = 0.5;
  
  if (value < 0) d *= -1.0;
  for (i = 0; i < places; i++) d/= 10.0;    
  tempfloat +=  d;
  if (value < 0) tempfloat *= -1.0;
  while ((tens * 10.0) <= tempfloat) 
  {
    tens *= 10.0;
    tenscount += 1;
  }
  if (value < 0) Serial.print('-');
  if (tenscount == 0) Serial.print(0, DEC);
  for (i=0; i< tenscount; i++) 
  {
    digit = (int) (tempfloat/tens);
    Serial.print(digit, DEC);
    tempfloat = tempfloat - ((float)digit * tens);
    tens /= 10.0;
  }
  if (places <= 0) return;
  Serial.print('.');  
  for (i = 0; i < places; i++) 
  {
    tempfloat *= 10.0; 
    digit = (int) tempfloat;
    Serial.print(digit,DEC);  
    tempfloat = tempfloat - (float) digit; 
  }
}
//=================================================
void NB_sendErrorMessage()
//=================================================
{
//  char msg[120];
//  sprintf(msg,"%d %d %s",NABTON_ERROR,g_error,g_errmsg);
//  L2_sendMsg(msg);
     digitalWrite(PIN_LED_STATUS,HIGH);
     Serial.print(NABTON_ERROR); Serial.print(" "); 
     Serial.print(g_error);      Serial.print(" "); 
     Serial.print(g_errmsg);     Serial.print(";");
     digitalWrite(PIN_LED_STATUS,LOW);
}
//=================================================
void NB_sendLogMessage()
//=================================================
{
//  char msg[120];
//  sprintf(msg,"%d %d %s",NABTON_LOG,g_log,g_logmsg);
//  L2_sendMsg(msg);
     digitalWrite(PIN_LED_STATUS,HIGH);
     Serial.print(NABTON_LOG); Serial.print(" "); 
     Serial.print(g_log);      Serial.print(" "); 
     Serial.print(g_logmsg);   Serial.print(";");
     digitalWrite(PIN_LED_STATUS,LOW);
}


//=================================================
void NB_countDownTime(int ixSid)
//=================================================
{
  int i;
  i= ixSid;

     g_now = millis();
     g_delta = g_now-g_last[i];
     if(g_delta > g_one_sec)
     {
       g_last[i] = millis();
       sprintf(dl[4],"%d",g_delta);
       g_sidCountDown[i]--; 
     }
}
//=================================================
void NB_sendToGwy(int sid, float data)
//=================================================
{
  int ixSid = 0,i;
  char msg[120];

  ixSid = 0;
  for(i=1;i<=SIDN;i++)
  {
     if(g_sids[i] == sid) ixSid = i; 
  }
  NB_countDownTime(ixSid);
  if(g_sidCountDown[ixSid] == 0)
  {
    g_sidCountDown[ixSid] = g_sidDelay[ixSid];
    if(g_error == 0)
    {
     g_counter++;
     digitalWrite(PIN_LED_STATUS,HIGH);
     Serial.print(NABTON_DATA);Serial.print(" "); 
     Serial.print(sid);Serial.print(" "); 
     Serial.print(NFLOAT);Serial.print(" "); 
     NB_printFloat(data,NFLOAT);
     Serial.print(";");NB_serialFlush();
     digitalWrite(PIN_LED_STATUS,LOW);
    }

    if (g_error != 0)
    {
      NB_sendErrorMessage();
      g_error = 0;
    }
    if (g_log != 0)
    {
      NB_sendLogMessage();
      g_log = 0;
    }
    delay(100);
    NB_recACK(sid);
  }
  else
    sprintf(dm[4],"***");
}
//=================================================
void NB_recACK(int expectedSid)
//=================================================
{

     int i,k,sid,ndata,unit,indexSid,sidGeneric,change;
     float tempC;
     char buffer[50];
     String str;
     int msg[100],ttemp,nx=0,ack=0;

     for(i=0;i<MAX_ORDERS;i++)
     {
        g_on[i] = 0;
        msg[i] = 0;
     }
     strcpy(buffer,"");

while(ack == 0)
{
  nx = Serial.available();
  if (nx > 0) 
  {
 
     Serial.readBytes(buffer,nx);
     for(i=0;i<nx;i++)
     {
       msg[i] = (int)(unsigned char)buffer[i]; 
     }
     
     if(msg[0] == NABTON_DATA_ACK)
     {
       sid = msg[1] + msg[2]*256;
       if(sid != expectedSid) 
       {
         sprintf(dr[2],"%d*",sid);
         sprintf(dr[4],"%d*",expectedSid);
         strcpy(g_errmsg,ERR_SID_MISMATCH);
         g_error = sid;
       }
       else
       {
         ack = 1;
         sprintf(dr[4],"[%d]",sid);
       }       

          // Find SID array index
     indexSid = 0;
     for(i=1;i<=SIDN;i++)
     {
       if(g_sids[i] == sid) indexSid = i; 
     }
       
       // SID exists!
       if(indexSid != 0)
       {
         k = 3;
         while(msg[k] != 0)
         {
           g_on[msg[k]] = 1;
           g_value[msg[k]] = msg[k+1];
           k = k + 2;
         }
         k = k-1;
         
         change = 0;
         if(g_on[ON_HB_VAL] == 1)
         { 
           g_sidHb[indexSid]     = g_value[ON_HB_VAL];
           change = 1;
         }
         if(g_on[ON_HB_UNIT] == 1)
         {
           g_sidHbUnit[indexSid] = g_value[ON_HB_UNIT];
           change = 1;
         }
         if(change == 1)
         {
           if(g_sidHbUnit[indexSid] == 1) unit = 1; // sec
           if(g_sidHbUnit[indexSid] == 2) unit = 60; //minute
           if(g_sidHbUnit[indexSid] == 3) unit = 60*60; // hour
           if(g_sidHbUnit[indexSid] == 4) unit = 24*60*60; //24h
           ttemp = g_sidHb[indexSid]*unit;
           if(ttemp > 4000000000) ttemp = 4000000000;       
           g_sidDelay[indexSid] = ttemp;  
           g_sidCountDown[indexSid] = ttemp;
         }
       } 
       else
       {
         strcpy(g_errmsg,ERR_SID_NOT_FOUND);
         g_error = sid;
       }    

     } 
     else
     {
         strcpy(g_logmsg,ERR_UNSUPPORTED_MESSAGE);
         g_log = msg[0];
     }
   NB_serialFlush();
  }
 } // ack

}
//=================================================
void NB_oledDraw() 
//=================================================
{
 u8g.firstPage();  
  do {
        draw();
  } while( u8g.nextPage() ); 
}
//=================================================
void NB_establishContact() 
//=================================================
{
 
 while (Serial.available() <= 0) 
 {
    Serial.print("X;"); 
    digitalWrite(PIN_LED_STATUS,HIGH);  delay(200);
    digitalWrite(PIN_LED_STATUS,LOW); 
    delay(1000);
 }
 NB_serialFlush();
}
//=================================================
void setup() {
//================================================= 
  Serial.begin(9600);
  NB_serialFlush();
  pinMode(PIN_LED_STATUS, OUTPUT);
  for(int i=1;i<=SIDN;i++)
  {
      g_sidDelay[i]     = 5;  
      g_sidCountDown[i] = 5;
      g_last[i] = millis(); 
  }
  
   // OLED
  if ( u8g.getMode() == U8G_MODE_R3G3B2 ) {
    u8g.setColorIndex(255);     // white
  }
  else if ( u8g.getMode() == U8G_MODE_GRAY2BIT ) {
    u8g.setColorIndex(3);         // max intensity
  }
  else if ( u8g.getMode() == U8G_MODE_BW ) {
    u8g.setColorIndex(1);         // pixel on
  }
  else if ( u8g.getMode() == U8G_MODE_HICOLOR ) {
    u8g.setHiColorByRGB(255,255,255);
  }
  strcpy(dr[2],"X_NB");
  strcpy(dm[3],"HS");
  strcpy(dr[3],"serv");
  
  NB_oledDraw();
  
  NB_establishContact(); 

  strcpy(dm[3],"");
  strcpy(dr[3],""); 
  sprintf(dm[4],"%d",g_counter);
  NB_oledDraw();
 
}

//=================================================
void loop()
//=================================================
{
    String str;
    //NB_countDownTime();
    NB_sendToGwy(SID1,x); 
    str = String(g_sidDelay[1]);
    str.toCharArray(dl[1],8); 
    str = String(g_sidCountDown[1]);
    str.toCharArray(dm[1],8); 
    str = String(x);
    str.toCharArray(dr[1],8); 
    
    NB_sendToGwy(SID2,x); 
    str = String(g_sidDelay[2]);
    str.toCharArray(dl[2],8); 
    str = String(g_sidCountDown[2]);
    str.toCharArray(dm[2],8); 
    str = String(x);
    str.toCharArray(dr[2],8); 
    
    NB_sendToGwy(SID3,x);   
    str = String(g_sidDelay[3]);
    str.toCharArray(dl[3],8); 
    str = String(g_sidCountDown[3]);
    str.toCharArray(dm[3],8); 
    str = String(x);
    str.toCharArray(dr[3],8); 
    sprintf(dm[4],"%d",g_counter);
    NB_oledDraw();
    x = x+0.001;
    if (x > 1000.0) x = 0;
    //delay(100);
}

